// 词频：列出一组文件或标准输入中每个单词出现的次数 .
// ./wf file1 file2 file3
// cat file1 | ./wf
#include "table.h"
#include "mem.h"
#include "atom.h"

#include "getword.h"

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

static int
first(int c)
{
    return isalpha(c);
}

static int
rest(int c)
{
    return isalpha(c) || c == '_';
}

static int
compare(const void *x, const void *y)
{
    return strcmp(*(char**)x, *(char**)y);
}

static void
vfree(const void *key, void **value, void *cl)
{
    (void)key;
    (void)cl;
    FREE(*value);
}

static void
wf(const char *name, FILE *fp)
{
    char buf[10240];
    Table_T table = Table_new(0, NULL, NULL);

    while (getword(fp, buf, sizeof(buf), first, rest)) {
        for (int i = 0; buf[i]; i++)
            buf[i] = tolower(buf[i]);
        const char *word = Atom_string(buf);

        int *count = (int*)Table_get(table, word);
        if (count == NULL) {
            NEW(count);
            *count = 1;
            Table_put(table, word, count);

        } else {
            (*count)++;
        }
    }

    if (name)
        printf("%s:\n", name);

    void **arr = Table_toArray(table, NULL);
    qsort(arr, Table_length(table), 2*sizeof(*arr), compare);

    for (int i = 0; arr[i]; i += 2) {
        printf("%10d\t%s\n", *(int*)arr[i+1], (char*)arr[i]);
    }
    FREE(arr);

    Table_map(table, vfree, NULL); // Not free atom
    Table_free(&table);
}

int main(int argc, char **argv)
{
    for (int i = 1; i < argc; i++) {
        FILE *fp = fopen(argv[i], "r");
        if (fp == NULL) {
            fprintf(stderr, "fail to open file:%s\n", argv[i]);
            continue;
        }

        wf(argv[i], fp);
        fclose(fp);
    }
    if (argc == 1)
        wf(NULL, stdin);
    return 0;
}

